﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TekaMUD.Engine.IO;
using System.Security.Cryptography;
using TekaMUD.Engine.Blocks;
using TekaMUD.Engine;
using TekaMUD.Engine.Framework;
using TekaMUD.Engine.Commands.Parser;

namespace TekaMUD.Engine.Commands
{
	public class PlayerMgmtCommands
	{
		public static string GetMOTD()
		{
			return "Welcome!\r\n\r\nEnter your name, or type NEW for a new player: ";
		}

		/// <summary>
		/// Called as the first handler for the channel.
		/// </summary>
		/// <param name="c"></param>
		[Obsolete("Controlar métodos para esconder o echo, por causa das passwords.")]
		public static void HandleName(Command c)
		{
			if (c.CommandNode is EmptyCommandNode)
			{
				c.Channel.WriteString("\nInvalid name. Enter your name, or type NEW for a new player: ");
				c.Player.Status = PlayerStatus.New;
				return;
			}
			if (c.CommandNode.FullText.ToLower() == "new")
			{
				c.Channel.WriteString("\nNew player registration\r\n");
				c.Channel.WriteString("Choose a login: ");

				c.Player.Status = PlayerStatus.Registering;
				c.Channel.PushNextHandler(new CommandHandler(HandleNewLogin));
			}
			else
			{
				c.Player.SetName(c.CommandNode.FullText.Trim());
				c.Channel.WriteString("Password: ");
				c.Player.Status = PlayerStatus.Registering;
				c.Channel.PushNextHandler(new CommandHandler(HandlerExistingPlayer));
			}
		}

		public static void HandlerExistingPlayer(Command c)
		{
			LoginResult lr = PlayerManager.Login(c.Channel.Player.Name, c.CommandNode.FullText);

			switch (lr.Result)
			{
				case LoginResultEnum.PlayerNotFound:
				case LoginResultEnum.PasswordInvalid:
					c.Channel.WriteString("\nInvalid login or password.\r\n");

					c.Player.InvalidLoginAttempts++;

					if (c.Player.InvalidLoginAttempts > 3)
					{
						c.Channel.WriteString("\nToo many login attempts. Closing connection.\r\n");
						c.Channel.Close();
					}
					else
					{
						// This forces the calling of the first handler again.
						c.Player.Status = PlayerStatus.New;
						c.Channel.WriteString("\nEnter your name, or type NEW for a new player: ");
					}

					return;

				case LoginResultEnum.Accepted:
					c.Channel.WriteString(string.Format("Welcome back {0}. Last login on {1}.\r\n", lr.Player.Name, lr.Player.LastLogin.ToString("d")));
					lr.Player.LastLogin = DateTime.Now;
					lr.Player.Status = TekaMUD.Engine.Blocks.PlayerStatus.Active;

					// Assign the loaded player to the channel.
					c.Channel.AssignPlayer(lr.Player);

					break;
			}
		}

		public static void HandleNewLogin(Command c)
		{
			if (c.CommandNode.FullText == null || c.CommandNode.FullText.Length == 0)
			{
				c.Channel.WriteString("\nInvalid name. Enter your name, or type NEW for a new player: ");
				c.Channel.PushNextHandler(new CommandHandler(HandleName));

				return;
			}

			if (c.CommandNode.FullText.Length > 12 || c.CommandNode.FullText.Length < 4)
			{
				c.Channel.WriteString("Invalid name length. Try again: ");
				c.Channel.PushNextHandler(new CommandHandler(HandleNewLogin));
				return;
			}

			foreach (char chr in c.CommandNode.FullText)
			{
				if (!Char.IsLetter(chr))
				{
					c.Channel.WriteString("Invalid character. Only letters allowed.\r\n");
					c.Channel.PushNextHandler(new CommandHandler(HandleNewLogin));

					return;
				}
			}

			// Name accepted.
			c.Player.SetName(c.CommandNode.FullText.Trim());
			c.Channel.WriteString("Enter your password: ");
			c.Channel.PushNextHandler(new CommandHandler(HandlePassword1));
		}

		public static void HandlePassword1(Command c)
		{
			// Password checks.
			if (c.CommandNode.FullText == null || c.CommandNode.FullText.Length < 3 || c.CommandNode.FullText.Length > 10)
			{
				c.Channel.WriteString("Password must have more than 3 characters and less than 10.\r\n");
				c.Channel.WriteString("Enter your password: ");
				c.Channel.PushNextHandler(new CommandHandler(HandlePassword1));
			}
			else
			{
				// Accepted.
				c.Channel.PushHelperString(c.CommandNode.FullText);
				c.Channel.WriteString("Please re-enter your password: ");
				c.Channel.PushNextHandler(new CommandHandler(HandlePassword2));
			}
		}

		public static void HandlePassword2(Command c)
		{
			string firstPassword = c.Channel.PopHelperString();

			if (c.CommandNode.FullText == null || !c.CommandNode.FullText.Equals(firstPassword))
			{
				c.Channel.WriteString("Password mismatch. Please try again\r\n");
				c.Channel.WriteString("Pick a password: ");

				c.Channel.PushNextHandler(new CommandHandler(HandlePassword1));
			}
			else
			{
				c.Player.PasswordHash = Crypto.GetMD5Hash(firstPassword);

				c.Channel.WriteString("\r\n");
				c.Channel.WriteString("Password accepted. Please enter your full name: ");

				c.Channel.PushNextHandler(new CommandHandler(HandleRegistrationFullname));
			}
		}

		[Obsolete("Name validations")]
		public static void HandleRegistrationFullname(Command c)
		{

			string name = c.CommandNode.FullText;

			if (name == null || name.Length < 5 || name.Length > 20)
			{
				c.Channel.WriteString("\r\n");
				c.Channel.WriteString("Invalid name lenght. Please enter your full name: ");
				c.Channel.PushNextHandler(new CommandHandler(HandleRegistrationFullname));
			}
			else
			{
				c.Channel.WriteString("Welcome!\r\n\r\n");
				c.Channel.SendPrompt();


				PlayerManager.Register(c.Player);
				c.Player.LastLogin = DateTime.Now;
				c.Player.RealName = c.CommandNode.FullText.Trim();
				c.Player.Status = TekaMUD.Engine.Blocks.PlayerStatus.Active;
				World.Current.AssignPlayerToRoom(World.Current.GetContinent("Europa").GetFirstSector().StartRoom, c.Player);
				c.Player.Channel = c.Channel;
			}
		}
	}
}
